Friday 11 February 2022

Web Tutorial: The Valentine Letter

Happy upcoming Valentine's Day, ya crazy lovebirds!

It's my pleasure, as always, to present the annual Valentine's Day web tutorial. This one is in standard HTML, CSS and JavaScript, and it will be a simple animation complete with graphics and a sappy love poem. We also want this animation to appear differently according to the time of day.

Ready? Here we go...

The images

For this, we will be using two pairs of backgrounds and one background for the love poem.

These are the sky backgrounds. They have been given a color adjustment in Photoshop, but are otherwise identical.

topbg_day.jpg

topbg_night.jpg



These are the earth backgrounds. They are PNG files with transparency.
middlebg_day.png

middlebg_night.png



This is the background image for the letter.

letterbg.jpg



The starting HTML is as follows.
<!DOCTYPE html>
<html>
    <head>
        <title>Valentine Letter</title>

        <style>

        </style>

        <script>

        </script>
    </head>

    <body>

    </body>
</html>


We set divs to have a translucent red background because there is going to be a fair amount of nesting.
<style>
    div {background: rgba(255, 0, 0, 0.2); }
</style>


Here, we define the function getTimeBg(). Leave it blank, for now.
<script>
    function getTimeBg()
    {

    }

</script>


The body needs to call this function upon loading.
<body onload="getTimeBg()">


Now for the divs! The first div has a CSS class of container.
<body onload="getTimeBg()">
    <div class="container">

    </div>

</body>


This is the styling for container. We want a specific width and height, and it will be set in the middle of the screen via the margin property. We will also give it a nice pink outline.
<style>
    div {background: rgba(255, 0, 0, 0.2); }

    .container
    {
        width: 800px;
        height: 700px;
        margin: 0 auto 0 auto;
        outline: 1px solid rgba(255, 100, 100, 1);
        overflow: hidden;
    }

</style>


Looking a little basic, right?


Now, add in two divs, wth CSS classes top and middle.
<div class="container">
    <div class="top">

    </div>

    <div class="middle">

    </div>

</div>


Here's the styling. They have 100% widths, but different heights. Also, middle has background properties that will fill the entire div. For now, we will leave the background image itself unspecified.
<style>
    div {background: rgba(255, 0, 0, 0.2); }

    .container
    {
        width: 800px;
        height: 700px;
        margin: 0 auto 0 auto;
        outline: 1px solid rgba(255, 100, 100, 1);
    }

    .top
    {
        width: 100%;
        height: 200px;
    }

    .middle
    {
        width: 100%;
        height: 850px;
        margin-top: -200px;
        background-size: cover;
        background-position: middle top;
        background-repeat: no-repeat;
    }

</style>


You can see where they line up.




Within the div styled using CSS class top, we have a div styled using CSS class sky.
<div class="top">
    <div class="sky" id="sky"></div>
</div>


This is the styling for sky. It takes up 400% of its parents width. The background-repeat property is set to repeat-x, because we want the sky background to stretch on forever horizontally.
.top
{
    width: 100%;
    height: 200px;
}

.sky
{
    width: 400%;
    height: 100%;
    background-position: left top;
    background-repeat: repeat-x;
}


See how this works? Don't worry about the content overflowing for the time being; I want you to have a clear visual of what is going on.




Now within the div styled by middle, we have another div styled using letter.
<div class="middle" id="earth">
    <div class="letter">

    </div>

</div>


Here are the CSS styles. letter has a specific width and height, and is set to the middle of its parent using the margin property. Its background is letterbg.jpg, and we set other properties to ensure it fills up the entire thing.
.sky
{
    width: 400%;
    height: 100%;
    background-position: left top;
    background-repeat: repeat-x;
    margin-left: 0px;    
}    

.middle
{
    width: 100%;
    height: 850px;
    margin-top: -200px;
    background-size: cover;
    background-position: middle top;
    background-repeat: no-repeat;
}

.letter
{
    width: 400px;
    height: 500px;
    margin: 0 auto 0 auto;
    background: url("letterbg.jpg");
    background-size: cover;
    background-position: middle top;
    background-repeat: no-repeat;
}


So far so good. We may need to make more adjustments later.




Yet aother div!
<div class="middle">
    <div class="letter">
        <div class="text">

        </div>    

    </div>
</div>


text
is for containing the poem, so we will make it even less wide than letter, set it in the middle using the margin property, and set font sizes.
.letter
{
    width: 400px;
    height: 500px;
    margin: 0 auto 0 auto;
    background: url("letterbg.jpg");
    background-size: cover;
    background-position: middle top;
    background-repeat: no-repeat;
}

.text
{
    width: 80%;
    margin: 0 auto 0 auto;
    font-family: georgia;
    font-size: 12px;
    font-weight: bold;
    line-height: 2.5em;
}


Now we will add two paragraph tags within the div styled using text. They will be styled using poem and author, respectively.
<div class="middle">
    <div class="letter">
        <div class="text">
            <p class="poem">

            </p>
            <p class="author">

            </p>
        </div>    
    </div>
</div>


Fill up the first p tag with the poem, and the second p tag with the author's name.
<div class="middle">
    <div class="letter">
        <div class="text">
            <p class="poem">
                <br />
                How do I love thee? Let me count the ways.<br />
                I love thee to the depth and breadth and height<br />
                My soul can reach, when feeling out of sight<br />
                For the ends of being and ideal grace.<br />
                I love thee to the level of every day's<br />
                Most quiet need, by sun and candle-light.<br />
                I love thee freely, as men strive for right.<br />
                I love thee purely, as they turn from praise.<br />
                I love thee with the passion put to use<br />
                In my old griefs, and with my childhood's faith.<br />
                I love thee with a love I seemed to lose<br />
                With my lost saints. I love thee with the breath,<br />
                Smiles, tears, of all my life; and, if God choose,<br />
                I shall but love thee better after death.<br />
            </p>
            <p class="author">
                - Elizabeth Barret Browning
            </p>

        </div>    
    </div>
</div>


Let's style those p tags. This is just for aesthetics.
.text
{
    width: 80%;
    margin: 0 auto 0 auto;
    font-family: georgia;
    font-size: 12px;
    font-weight: bold;
    line-height: 2.5em;
}

.poem
{
    font-style: italic;
}

.author
{
    text-align: right;
}


Here we go!




The backgrounds

First, we add ids to the divs that we need to set backgrounds for.
<div class="top">
    <div class="sky" id="sky"></div>
</div>

<div class="middle" id="earth">


Next, we add in some script. We first get sky and earth using the getElementById() method. Then we get the date using new Date() and assign it to the variable d.
function getTimeBg()
{
    var sky = document.getElementById("sky");
    var earth = document.getElementById("earth");

    var d = new Date();

}


Set an If block, that examines the output of the getHours() method. If the time of the day is between 6 AM and 6 PM (i.e, d.getHours() is between 6 to 18 inclusive), we use the day versions of the backgrounds. If not, we use the night versions.
function getTimeBg()
{
    var sky = document.getElementById("sky");
    var earth = document.getElementById("earth");

    var d = new Date();
    if (d.getHours() >= 6 && d.getHours() <= 18) {
        sky.style.background = "url(topbg_day.jpg)";
        earth.style.background = "url(middlebg_day.png)";
    }
    else
    {
        sky.style.background = "url(topbg_night.jpg)";
        earth.style.background = "url(middlebg_night.png)";
    }

}


It's now 11 PM where I am, so the night versions are on!




At this point, we should be turning off the background color of the divs.
div {background: rgba(255, 0, 0, 0); }


Also, add breaks here to adjust the content. It's a really lazy way, I know.
<div class="middle" id="earth">
    <br /><br /><br /><br /><br /><br /><br /><br /><br />
    <div class="letter">






Animating the sky
For this, we will use CSS3 animations. This will go right into the CSS class sky. We use an animation name, skymove, which we will expand on later, and set a duration. Make this fast, maybe 1 second, so we can check on the smoothness of the animation. The iteration count is set to infinite so that it will go on forever, and we'll set the timing function to linear so that there won't be any acceleration or deceleration of the animation. It will be at a constant speed.
.sky
{
    width: 400%;
    height: 100%;
    background-position: left top;
    background-repeat: repeat-x;
    margin-left: 0px;
    animation-name: skymove;
    animation-duration: 1s;    
    animation-iteration-count: infinite;
    animation-timing-function: linear;    

}


Now we will define skymove. At 100%, the margin-left property is set to minus twice the width of the background, which is minus 1600 pixels.
.sky
{
    width: 400%;
    height: 100%;
    background-position: left top;
    background-repeat: repeat-x;
    margin-left: 0px;
    animation-name: skymove;
    animation-duration: 1s;    
    animation-iteration-count: infinite;
    animation-timing-function: linear;    
}

@keyframes skymove
{
    0%   {margin-left: 0px;}
    100% {margin-left: -1600px;}
}        


Now the sky div moves left! You can see that the animation appears infinite due to the background-repeat property being set to repeat-x.




Set the overflow property of these classes to hidden.
.container
{
    width: 800px;
    height: 700px;
    margin: 0 auto 0 auto;
    outline: 1px solid rgba(255, 100, 100, 1);
    overflow: hidden;
}

.top
{
    width: 100%;
    height: 200px;
    overflow: hidden;
}


Ah, great stuff! Now that the overflow property is set to hidden, it looks like the sky is animated! You may want to make the animation slower, maybe set the duration to 200 seconds or something.




Final loving words

I know I know, this Valentine's day web tutorial is kind of corny. But hey, they can't all be winners. And let's face it, Valentine's Day can be pretty corny.

Did the earth sky move for you? Heh heh.
T___T

No comments:

Post a Comment